/**
 * 文件下载类
 * @author 郑翎
 * 2015-10-1 11:07:43
 */
package com.cbts.action.travel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.cbts.entity.ReceiptId;
import com.cbts.service.travel.ApplayReimService;
import com.opensymphony.xwork2.ActionSupport;


@SuppressWarnings("serial")
public class DownloadAction extends ActionSupport {

    private String   filenames;
    private String   filepaths;
    private String[] filenameArray = null;
    private String[] filepathArray = null;
    private String   filename;
    private String   filepath;
    private String travelorder;
    private ApplayReimService  applayReimService;
    private SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        
	public String getTravelorder() {
		return travelorder;
	}
	public void setTravelorder(String travelorder) {
		this.travelorder = travelorder;
	}
	
	
	public ApplayReimService getApplayReimService() {
		return applayReimService;
	}
	public void setApplayReimService(ApplayReimService applayReimService) {
		this.applayReimService = applayReimService;
	}
	/**
     * 得到客户端请求的文件名字符串
     * @author lynn
     * @return 客户端请求的文件名字符串

     */
    public String getFilenames() {
        return filenames;
    }
    /**
     * 将客户端请求的文件名字符串set到filenames变量
     * @author lynn
     * @param filenames
     * 2009-10-30   下午11:21:34
     */
    public void setFilenames(String filenames) {
        this.filenames = filenames;
        filenameArray = null ;
        if (this.filenames.contains("|")) {
            parseFilenamesToArray();
        }
    }
    /**
     * 得到客户端请求的文件路径字符串
     * @author lynn
     * @return 客户端请求的文件路径字符串

     */
    public String getFilepaths() {
        return filepaths;
    }
    /**
     * 将客户端请求的文件路径字符串set到filepaths变量
     * @author lynn
     * @param filepaths
     * 2009-10-30   下午11:21:40
     */
    public void setFilepaths(String filepaths) {
        this.filepaths = filepaths;
        filepathArray = null;
        if (this.filepaths.contains("|")) {
            parseFilepathsToArray();
        }else {
        	Map session = ServletActionContext.getContext().getSession();
        	String fileuserid = session.get("fileuserid").toString();
        	this.filepaths = "/files/"+fileuserid+"/"+this.filepaths;
		}
    }
    
    
    
    /**
     * 解析客户端请求下载的文件名
     * @author lynn
     */
    public void parseFilenamesToArray() {
    	try {
    		filenames = new String(filenames.getBytes("ISO-8859-1"),"utf-8");
    		System.err.println("filenameArray"+filenames);
		} catch (Exception e) {
			// TODO: handle exception
		}
        filenameArray = filenames.split("\\|");
    }
    /**
     * 解析客户端请求下载的文件路径
     * @author lynn
     */
    public void parseFilepathsToArray() {
    	try {
    		filepaths = new String(filepaths.getBytes("ISO-8859-1"),"utf-8");
		} catch (Exception e) {
			// TODO: handle exception
		}
        filepathArray = filepaths.split("\\|");
        Map session = ServletActionContext.getContext().getSession();
    	String userid = session.get("userid").toString();
        String dowloadfiles= "/files/"+userid+"/";
        for (int i = 0; i < filepathArray.length; i++) {
        	
        	this.filepathArray[i] = dowloadfiles+this.filepathArray[i];
		}
    }
    
    
    /**
     *  得到下载显示名,对就struts.xml配置文件<param name="contentDisposition">attachment;filename=${filename}</param>
     *  要想正确的显示中文文件名，我们需要对fileName再次编码 否则中文名文件将出现乱码，或无法下载的情况
     * @author lynn
     * @return 返回下载显示名
     */
    public String getFilename() {
        try {
            return new String(filename.getBytes(), "ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return filename;
        }
    }
    
    
    /** 
     *  得到下载文件路径
     * @author lynn
     * @return 返回下载路径
     */
    public String getFilepath(){
        return filepath;
    }
    
    /**
     * 初始化下载文件名
     * @author lynn
     */
    public void initFilename() {
        if(isBaleZip()){
            this.filename = "批量打包下载.zip";
        }else{
            
            try {
            	this.filename = new String(getFilenames().getBytes("ISO-8859-1"),"utf-8");
            	this.filename = this.filename.replace(" ", "");
			} catch (Exception e) {
				this.filename = getFilenames();
			}
        }
        System.out.println("下载文件名:    "+this.filename);
    }
    
    
    /**
     *  初始化下载路径
     * @author lynn
     */
    public void initFilepath() {
        if(isBaleZip()){
        	//创建临时文件夹
            String rootpath = ServletActionContext.getServletContext().getRealPath("/tempfile");
            File dir = new File(rootpath);
            if (dir.exists() == false) {
             dir.mkdirs();
            }
            
            String requestip = ServletActionContext.getRequest().getLocalAddr();
            //this.filepath = "c:\\批量打包下载.zip";
            this.filepath = rootpath+"\\"+requestip+"-"+format.format(new Date())+".zip";
            System.err.println("下载文件路径zip:    "+this.filepath);
        }else{
            this.filepath = getFilepaths();
            try {
            	this.filepath = new String(getFilepaths().getBytes("ISO-8859-1"),"utf-8");
    		} catch (Exception e) {
    			this.filepath = getFilepaths();
    		}
        }
        
        System.out.println("下载文件路径:    "+this.filepath);
    }

    
    /**
     * 判断是否符合打包要求
     * @author lynn
     * @return 否符合打包要求
     */
    public  boolean isBaleZip(){
        boolean isZip = false;
        if(this.filenameArray!= null && this.filepathArray!= null && this.filenameArray.length>1 && this.filenameArray.length==this.filepathArray.length){
             isZip =  true;
        }
        return isZip;
    }
    
    
    /**
     * 压缩文件
     * @author lynn
     * @param zipFilePath  产生的压缩文件路径和名字
     * @param names        传入要进行打包的所有文件名
     * @param paths        传入要进行打包的所有文件路径
     * @throws IOException
     */
    public void baleZip(String zipFilePath,String[] names,String[] paths) throws IOException{
        File f = new File(zipFilePath);
        f.createNewFile();
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f));
        //创建压缩文件夹
        out.putNextEntry(new ZipEntry("/"));
        for(int i=0;i<paths.length;i++){
        	//创建文件
            out.putNextEntry(new ZipEntry(names[i])); 
            InputStream in =ServletActionContext.getServletContext().getResourceAsStream(paths[i]);
            int b;
            while ((b = in.read()) != -1) {
            	//将in中的数据写入创建好的文件中
                out.write(b);
            }
            in.close();
        }
         out.flush();
         out.close();
    }
    
    
    
    
    /**
     *  返回目标下载文件输入流跟struts2,然后struts2再生成输出流,对应struts.xml的<param name="inputName">downloadFile </param>
     *  但是struts2后台不可能一次性将我们的输入流输出到输出流里面.. 而我们也就是不好控制,例在何时删除产生的临时文件
     * @author lynn
     * @return 目标下载文件输入流
     */
    public InputStream getDownloadFile(){
    	
        initFilename();
        initFilepath();
        InputStream in = null;
        File tempfile = null;
        if(isBaleZip()){
            try {
                baleZip(this.filepath,this.filenameArray,this.filepathArray);
               
                tempfile = new File(this.filepath);
                in =  new FileInputStream(tempfile);
                
            } catch (IOException e) {
                System.out.println(e.getMessage()+"   "+"压缩文件出错!!");
                return null;
            } finally{
                if(tempfile.exists()){
                    tempfile.delete();
                    if(tempfile.exists()){
                        System.out.println("------删除临时文件失败-------");
                        HttpServletRequest request = ServletActionContext.getRequest();
                    	HttpSession session = request.getSession();
                    	session.setAttribute("tempfilePath", filepath);
                    }else{
                        System.out.println("------删除打包产生的临时文件------");
                    }
                }
            }
        }else{
            in  = ServletActionContext.getServletContext().getResourceAsStream(getFilepath());
        }
        return in;
    }
    
    
    
    /**
     * 而这种文件下载方式却是存在安全隐患的， 因为访问者如果精通Struts2的话，它可能使用这样的带有表单参数的地址来访问：
     * http://localhost:8080/disasterSystem/download.action?filename=%E6%B5%8B%E8%AF%95%E4%B8%8B%E8%BD%BD&filepath=/WEB-INF/web.xml
     * 这样的结果就是下载后的文件内容是您系统里面的web.xml的文件的源代码，甚至还可以用这种方式来下载任何其它JSP文件的源码, 这对系统安全是个很大的威胁。
     * 作为一种变通的方法，读者最好是从数据库中进行路径配置，然后把Action类中的设置inputPath的方法统统去掉，简言之就是所有set方法定义
     * 第二种方法,读者可以在execute()方法中进行路径检查，如果发现有访问不属于download下面文件的代码，就一律拒绝，不给他们返回文件内容。
     * 
     * @author lynn
     * @param filepath
     */
    @Override
    public String execute() throws Exception {
        // 文件下载目录路径
        return SUCCESS;
    }
    //删除文件
    public String deleteFile() {
    	
    	initFilename();
    	initFilepath();
        ReceiptId receiptId = new ReceiptId(travelorder, this.filename);
        String delfile = ServletActionContext.getServletContext().getRealPath(this.filepath);
        
        if (deleteFile(delfile))
        {
        	if (applayReimService.deleteReceipt(receiptId))
        		return "delsuc";
        	else
        		return "delerr";	
        }
        else
        	return "delerr";
	}
    /** 
     * 删除单个文件 
     * @param   sPath    被删除文件的文件名 
     * @return 单个文件删除成功返回true，否则返回false 
     */  
    public boolean deleteFile(String sPath) {  
        boolean flag = false;  
        File file = new File(sPath);  
        // 路径为文件且不为空则进行删除  
        if (file.isFile() && file.exists()) {  
            file.delete();  
            flag = true;  
        }  
        return flag;  
    }
}